﻿using System;
using System.Net;
using System.IO;
using System.Net.Cache;

namespace NeroConnect.Network
{
	/// <summary>Makes a HTTP request to a URL.</summary>
	public interface IRequest
	{
		/// <summary>Gets a value that indicates whether a response has been received from an Internet resource.</summary>
		/// <value>true if a response has been received; otherwise, false.</value>
		bool HaveResponse { get; }

		/// <summary>Specifies a collection of the name/value pairs that make up the HTTP headers.</summary>
		/// <value>A System.Net.WebHeaderCollection that contains the name/value pairs that make up the headers for the HTTP request.</value>
		/// <exception cref="System.InvalidOperationException">The request has been started by calling the GetRequestStream(), BeginGetRequestStream(System.AsyncCallback,System.Object), GetResponse(), or BeginGetResponse(System.AsyncCallback,System.Object) method.</exception>
		WebHeaderCollection Headers { get; }

		/// <summary>
		/// Gets the cookies associated with the request.
		/// </summary>
		/// <value>A System.Net.CookieContainer that contains the cookies associated with this request.</value>
		CookieContainer CookieContainer { get; set; }

		/// <summary>Gets or sets the method for the request.</summary>
		/// <value>The request method to use to contact the Internet resource. The default value is GET.</value>
		/// <exception cref="System.ArgumentException">No method is supplied.-or- The method string contains invalid characters.</exception>
		string Method { get; set; }

		/// <summary>Gets the original Uniform Resource Identifier (URI) of the request.</summary>
		/// <value>A System.Uri that contains the URI of the Internet resource passed to the IFactory.Create(System.String) method.</value>
		Uri RequestUri { get; }

		/// <summary>Gets or sets the time-out value in milliseconds for the GetResponse() and GetRequestStream() methods.</summary>
		/// <value>The number of milliseconds to wait before the request times out. The default value is 100,000 milliseconds (100 seconds).</value>
		/// <exception cref="System.ArgumentOutOfRangeException">The value specified is less than zero and is not System.Threading.Timeout.Infinite.</exception>
		int Timeout { get; set; }

		/// <summary>Gets or sets the Content-length HTTP header.</summary>
		/// <value>The number of bytes of data to send to the Internet resource. The default is -1, which indicates the property has not been set and that there is no request data to send.</value>
		/// <exception cref="System.InvalidOperationException">The request has been started by calling the GetRequestStream(), BeginGetRequestStream(System.AsyncCallback,System.Object), GetResponse(), or BeginGetResponse(System.AsyncCallback,System.Object) method.</exception>
		/// <exception cref="System.ArgumentOutOfRangeException">The new ContentLength value is less than 0.</exception>
		long ContentLength { get; set; }

		/// <summary>Gets or sets the value of the Content-type HTTP header.</summary>
		/// <value>The value of the Content-type HTTP header. The default value is null.</value>
		string ContentType { get; set; }

		///// <summary>Get or set the Date HTTP header value to use in an HTTP request.</summary>
		///// <value>The Date header value in the HTTP request.</value>
		//DateTime Date { get; set; }

		/// <summary>Gets or sets a value that indicates whether to make a persistent connection to the Internet resource.</summary>
		/// <value>true if the request to the Internet resource should contain a Connection HTTP header with the value Keep-alive; otherwise, false. The default is true.</value>
		bool KeepAlive { get; set; }

		/// <summary>Gets or sets the value of the Transfer-encoding HTTP header.</summary>
		/// <value>The value of the Transfer-encoding HTTP header. The default value is null.</value>
		/// <exception cref="System.InvalidOperationException">TransferEncoding is set when SendChunked is false.</exception>
		/// <exception cref="System.ArgumentException">TransferEncoding is set to the value "Chunked".</exception>
		string TransferEncoding { get; set; }

		/// <summary>Gets or sets the value of the User-agent HTTP header.</summary>
		/// <value>The value of the User-agent HTTP header. The default value is null.</value>
		/// <remarks>The value for this property is stored in System.Net.WebHeaderCollection. If WebHeaderCollection is set, the property value is lost.</remarks>
		string UserAgent { get; set; }

		/// <summary>Gets or sets the value of the If-Modified-Since HTTP header.</summary>
		/// <value>A System.DateTime that contains the contents of the If-Modified-Since HTTP header. The default value is the current date and time.</value>
		DateTime IfModifiedSince { get; set; }

		/// <summary>Gets or sets a value that indicates whether to send data in segments to the Internet resource.</summary>
		/// <value>true to send data to the Internet resource in segments; otherwise, false. The default value is false.</value>
		/// <exception cref="System.InvalidOperationException">The request has been started by calling the System.Net.HttpWebRequest.GetRequestStream(), System.Net.HttpWebRequest.BeginGetRequestStream(System.AsyncCallback,System.Object), System.Net.HttpWebRequest.GetResponse(), or System.Net.HttpWebRequest.BeginGetResponse(System.AsyncCallback,System.Object) method.</exception>
		bool SendChunked { get; set; }

		/// <summary>Begins an asynchronous request for a System.IO.Stream object to use to write data.</summary>
		/// <param name="callback">The System.AsyncCallback delegate.</param>
		/// <param name="state">The state object for this request.</param>
		/// <returns>An System.IAsyncResult that references the asynchronous request.</returns>
		/// <exception cref="System.Net.ProtocolViolationException">The Method property is GET or HEAD.-or- KeepAlive is true, AllowWriteStreamBuffering is false, ContentLength is -1, SendChunked is false, and Method is POST or PUT.</exception>
		/// <exception cref="System.InvalidOperationException">The stream is being used by a previous call to BeginGetRequestStream(System.AsyncCallback,System.Object)-or- TransferEncoding is set to a value and SendChunked is false.-or- The thread pool is running out of threads.</exception>
		/// <exception cref="System.NotSupportedException">The request cache validator indicated that the response for this request can be served from the cache; however, requests that write data must not use the cache. This exception can occur if you are using a custom cache validator that is incorrectly implemented.</exception>
		/// <exception cref="WebException">Abort() was previously called.</exception>
		/// <exception cref="System.ObjectDisposedException">In a .NET Compact Framework application, a request stream with zero content length was not obtained and closed correctly. For more information about handling zero content length requests, see Network Programming in the .NET Compact Framework.</exception>
		IAsyncResult BeginGetRequestStream(AsyncCallback callback, object state);

		/// <summary>Begins an asynchronous request to an Internet resource.</summary>
		/// <param name="callback">The System.AsyncCallback delegate</param>
		/// <param name="state">The state object for this request.</param>
		/// <returns>An System.IAsyncResult that references the asynchronous request for a response.</returns>
		/// <exception cref="System.InvalidOperationException">The stream is already in use by a previous call to BeginGetResponse(System.AsyncCallback,System.Object)-or- TransferEncoding is set to a value and SendChunked is false.-or- The thread pool is running out of threads.</exception>
		/// <exception cref="System.Net.ProtocolViolationException">Method is GET or HEAD, and either ContentLength is greater than zero or SendChunked is true.-or- KeepAlive is true, AllowWriteStreamBuffering is false, and either ContentLength is -1, SendChunked is false and Method is POST or PUT.</exception>
		/// <exception cref="WebException">Abort() was previously called.</exception>
		IAsyncResult BeginGetResponse(AsyncCallback callback, object state);

		/// <summary>Ends an asynchronous request for a System.IO.Stream object to use to write data.</summary>
		/// <param name="asyncResult">The pending request for a stream.</param>
		/// <returns>A System.IO.Stream to use to write request data.</returns>
		/// <exception cref="System.ArgumentNullException">asyncResult is null.</exception>
		/// <exception cref="System.IO.IOException">The request did not complete, and no stream is available.</exception>
		/// <exception cref="System.ArgumentException">asyncResult was not returned by the current instance from a call to BeginGetRequestStream(System.AsyncCallback,System.Object).</exception>
		/// <exception cref="System.InvalidOperationException">This method was called previously using asyncResult.</exception>
		/// <exception cref="WebException">Abort() was previously called.-or- An error occurred while processing the request.</exception>
		Stream EndGetRequestStream(IAsyncResult asyncResult);

		/// <summary>Ends an asynchronous request to an Internet resource.</summary>
		/// <param name="asyncResult"> The pending request for a response.</param>
		/// <returns>A IResponse that contains the response from the Internet resource.</returns>
		/// <exception cref="System.ArgumentNullException">asyncResult is null.</exception>
		/// <exception cref="System.InvalidOperationException">This method was called previously using asyncResult.-or- The ContentLength property is greater than 0 but the data has not been written to the request stream.</exception>
		/// <exception cref="WebException">Abort() was previously called.-or- An error occurred while processing the request.</exception>
		/// <exception cref="System.ArgumentException">asyncResult was not returned by the current instance from a call to BeginGetResponse(System.AsyncCallback,System.Object).</exception>
		IResponse EndGetResponse(IAsyncResult asyncResult);

		/// <summary>Gets a System.IO.Stream object to use to write request data.</summary>
		/// <returns>A System.IO.Stream to use to write request data.</returns>
		/// <exception cref="System.Net.ProtocolViolationException">The Method property is GET or HEAD.-or- KeepAlive is true, AllowWriteStreamBuffering is false, ContentLength is -1, SendChunked is false, and Method is POST or PUT.</exception>
		/// <exception cref="System.InvalidOperationException">The GetRequestStream() method is called more than once.-or- TransferEncoding is set to a value and SendChunked is false.</exception>
		/// <exception cref="System.NotSupportedException">The request cache validator indicated that the response for this request can be served from the cache; however, requests that write data must not use the cache. This exception can occur if you are using a custom cache validator that is incorrectly implemented.</exception>
		/// <exception cref="WebException">Abort() was previously called.-or- The time-out period for the request expired.-or- An error occurred while processing the request.</exception>
		/// <exception cref="System.ObjectDisposedException">In a .NET Compact Framework application, a request stream with zero content length was not obtained and closed correctly. For more information about handling zero content length requests, see Network Programming in the .NET Compact Framework.</exception>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
		Stream GetRequestStream();

		/// <summary>Returns a response from an Internet resource.</summary>
		/// <returns>A IResponse that contains the response from the Internet resource.</returns>
		/// <exception cref="System.InvalidOperationException">The stream is already in use by a previous call to BeginGetResponse(System.AsyncCallback,System.Object).-or- TransferEncoding is set to a value and SendChunked is false.</exception>
		/// <exception cref="System.Net.ProtocolViolationException">Method is GET or HEAD, and either ContentLength is greater or equal to zero or SendChunked is true.-or- KeepAlive is true, AllowWriteStreamBuffering is false, ContentLength is -1, SendChunked is false, and Method is POST or PUT.</exception>
		/// <exception cref="System.NotSupportedException">The request cache validator indicated that the response for this request can be served from the cache; however, this request includes data to be sent to the server. Requests that send data must not use the cache. This exception can occur if you are using a custom cache validator that is incorrectly implemented.</exception>
		/// <exception cref="WebException">Abort() was previously called.-or- The time-out period for the request expired.-or- An error occurred while processing the request.</exception>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
		IResponse GetResponse();

		/// <summary>Gets the service point to use for the request.</summary>
		/// <value>A System.Net.ServicePoint that represents the network connection to the Internet resource.</value>
		ServicePoint ServicePoint { get; }

		/// <summary>Cancels a request to an Internet resource.</summary>
		void Abort();

		/// <summary>Adds a byte range header to a request for a specific range from the beginning or end of the requested data.</summary>
		/// <param name="range">The starting or ending point of the range.</param>
		/// <exception cref="System.ArgumentException">range is invalid</exception>
		/// <exception cref="System.InvalidOperationException">The range header could not be added.</exception>
		void AddRange(int range);

		/// <summary>Adds a byte range header to the request for a specified range.</summary>
		/// <param name="from">The position at which to start sending data.</param>
		/// <param name="to">The position at which to stop sending data.</param>
		/// <exception cref="System.ArgumentException">The specified range is invalid</exception>
		/// <exception cref="System.ArgumentOutOfRangeException">from is greater than to -or- from or to is less than 0.</exception>
		/// <exception cref="System.InvalidOperationException">The range header could not be added.</exception>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "To")]
		void AddRange(int from, int to);

		/// <summary>Gets or sets proxy information for the request.</summary>
		/// <value>The System.Net.IWebProxy object to use to proxy the request. The default value is set by calling the System.Net.GlobalProxySelection.Select property.</value>
		/// <exception cref="System.ArgumentNullException">System.Net.HttpWebRequest.Proxy is set to null.</exception>
		/// <exception cref="System.InvalidOperationException">The request has been started by calling System.Net.HttpWebRequest.GetRequestStream(), System.Net.HttpWebRequest.BeginGetRequestStream(System.AsyncCallback,System.Object), System.Net.HttpWebRequest.GetResponse(), or System.Net.HttpWebRequest.BeginGetResponse(System.AsyncCallback,System.Object).</exception>
		/// <exception cref="System.Security.SecurityException">The caller does not have permission for the requested operation.</exception>
		IWebProxy Proxy { get; set; }

		/// <summary>Gets or sets the cache policy for this request.</summary>
		/// <value>A System.Net.Cache.RequestCachePolicy object that defines a cache policy.</value>value>
		RequestCachePolicy CachePolicy { get; set; }
	}
}
